#include "header.h"
#include "modules.h"
#include "extern.h"
#include "str.h"
#include "linkedlists.h"
#include "types.h"

void module_load_all (void)
{
 const char* modpath = "modules/";
 DIR* moddir = NULL;
 struct dirent *rd = NULL;
 char FullModuleName[64+1];

	moddir = opendir (modpath);
		if (moddir == NULL)
		{
			printf ("%s modules dir not found\n", modpath);/*<----------------------------------------------------------*/
		}
		else
		{
			while ((rd = readdir (moddir)) != NULL){
				if ((strcmp (rd->d_name, ".") != 0)
					&& (strcmp (rd->d_name, "..") != 0)
					&& (rd->d_name[strlen(rd->d_name)-1]=='o')
					&& (rd->d_name[strlen(rd->d_name)-2]=='s')
					&& (rd->d_name[strlen(rd->d_name)-3]=='.')
					){
					sprintf (FullModuleName, "%s%s", modpath, rd->d_name);
					module_load (FullModuleName);
				}
			}
			closedir (moddir);
		}
}

void module_clear_all (void)
{
 Module *mod = NULL;

	while ((mod = List_PopHead(modules_list)) != NULL){
			module_clear (mod);
			free (mod);
	}
}

void module_load (const char* path)
{
 void *id = NULL;
 Module *module = NULL;
 void (*init)() = NULL;
 char *error = NULL;

	id = dlopen (path, RTLD_NOW | RTLD_GLOBAL);
		if (id == NULL)
		{
			fprintf (stderr, "dlopen() :%s: %s\n", path, dlerror());
			free (module);
		}
		else
		{
			dlerror();
			init = dlsym (id, "aures_init");
				if ((error = dlerror()) != NULL)
				{
					fprintf (stderr, "dlsym(): %s\n", error);
				}
				else
				{
					module = module_new (id);
						if (module != NULL){
							init(module);
							strncpy (module->fullpath, path, strlen (path));
							List_PushTail (modules_list, module);
							fprintf (stdout, "Module : %s\n", module->name);
							fprintf (stdout, "Version: %s\n", module->version);
							fprintf (stdout, "Author : %s\n", module->author);
							fprintf (stdout, "Desc   : %s\n", module->desc);
							fprintf (stdout, "%s loaded\n", path);
						}
				}
		}
}

void module_clear (Module *module)
{

 void (*clear)();
 char* err = NULL;

	dlerror();
	clear = dlsym (module->id, "aures_cleanup");
		if ((err = dlerror()) != NULL){
			fprintf (stderr, "dlsym() :%s\n", err);
		}
		else
		{
			clear();
			dlclose (module->id);
		}
}

Module* module_new (void* id)
{
 Module* module = NULL;

	module = malloc (sizeof (*module));
		if (module == NULL)
		{
			printf ("couldn't alloc: NewModule()\n");
		}
		else
		{
			module->id = id;
		}

 return module;
}

Module* module_find (const char* modname)
{
	Module *mod = List_InitIter (modules_list);
	while ((mod != NULL) && (strncmp (mod->name, modname, strlen (mod->name)) == 0))
		mod = List_IterNext (modules_list);

 return (mod);
}

void module_del (const char* modname)
{
	Module *mod = List_InitIter (modules_list);
	while (mod != NULL)
	{
		if (strncmp (mod->name, modname, strlen (mod->name)) == 0){
			module_clear (mod);
			free (mod);
			break;
		}
		mod = List_IterNext (modules_list);
	}

}
